﻿using System;
using System.Linq;
using System.Data.SqlClient;
using YmtAuth.Domain.EventHistory;
using YmtAuth.Domain.Repository;
using YmtAuth.Repository.Mongodb;
using System.Threading;
using YmtSystem.CrossCutting;
using System.Configuration;
using System.Diagnostics;
using YmtAuth.Domain.Model.YmatouUserBills.TencentLoginProtection;
using Ymatou.Counter.Client40;
using Ymatou.Counter.Contract;
using Ymatou.ServiceCenter;


namespace YmtAuth.Repository.YmtAuthDomainRepository
{
    public class YmtUserLoginHistoryRepository : Repository_v1<YmtUserLoginEvent, string>,
        IYmtUserLoginHistoryRepository
    {
        public YmtUserLoginHistoryRepository()
            : base(new DbContext("LoginLogMongoUrl"))
        {

        }

        public void LogAsync(YmtUserLoginEvent @event)
        {
            AddAsync(@event
                    , "Ymt_LoginHistory"
                    , "LoginHistory"
                    , ex => YmatouLoggingService.Error("YmtUserLoginHistoryRepository AsyncLog error {0}", ex)
                    , new CancellationTokenSource(3000).Token);
        }

        public async void UpdateLoginTimeAsync(int userId)
        {
            using (var sqlConn = new SqlConnection())
            {
                try
                {
                    var timeOutVal = ConfigurationManager.AppSettings["UpdateLogintimeTimeout"].ConvertToInt32(2000);

                    var tokenSource = new CancellationTokenSource(timeOutVal);
                    var token = tokenSource.Token;

                    if (!token.IsCancellationRequested)
                    {
                        var connStr =
                            ConfigurationManager.ConnectionStrings["YmatouUserConnectionString"].ConnectionString;
                        if (string.IsNullOrEmpty(connStr))
                        {
                            return;
                        }
                        sqlConn.ConnectionString = connStr;
                        if (sqlConn.State != System.Data.ConnectionState.Open)
                            await sqlConn.OpenAsync(token);

                        var command = sqlConn.CreateCommand();
                        command.CommandText = "update Ymt_Users set dLastLoginTime=getdate() where iUserId=" + userId;
                        await command.ExecuteNonQueryAsync(token).ConfigureAwait(false);
                    }
                }
                catch (AggregateException ex)
                {
                    foreach (var item in ex.InnerExceptions)
                    {
                        YmatouLoggingService.Error("YmtUserLoginHistoryRepository AsyncUpdateLoginTime error-0 {0}",
                            item);
                    }
                }
                catch (Exception ex)
                {
                    YmatouLoggingService.Error("YmtUserLoginHistoryRepository AsyncUpdateLoginTime error-1 {0}", ex);
                }
                finally
                {
                    if (sqlConn != null && sqlConn.State == System.Data.ConnectionState.Open)
                        sqlConn.Close();
                }
            }
        }

        public async void SaveTencentLoginProtectionResult(TencentLoginProtectionEvent @event)
        {
            using (var sqlConn = new SqlConnection())
            {
                try
                {
                    var timeOutVal = ConfigurationManager.AppSettings["UpdateLogintimeTimeout"].ConvertToInt32(2000);

                    var tokenSource = new CancellationTokenSource(timeOutVal);
                    var token = tokenSource.Token;

                    if (!token.IsCancellationRequested)
                    {
                        var connStr =
                            ConfigurationManager.ConnectionStrings["YmatouUserConnectionString"].ConnectionString;
                        if (string.IsNullOrEmpty(connStr))
                        {
                            return;
                        }
                        sqlConn.ConnectionString = connStr;
                        if (sqlConn.State != System.Data.ConnectionState.Open)
                            await sqlConn.OpenAsync(token);

                        var command = sqlConn.CreateCommand();
                        command.CommandText =
                            string.Format(
                                "INSERT INTO [dbo].[Ymt_TencentLoginProtection] VALUES ('{0}','{1}','{2}',{3},{4},{5},'{6}',{7})",
                                @event.Id, @event.LoginId, @event.LoginIp, @event.LoginTime,
                                @event.Result, @event.Code, @event.Message, @event.Level);
                        await command.ExecuteNonQueryAsync(token).ConfigureAwait(false);
                    }
                }
                catch (AggregateException ex)
                {
                    foreach (var item in ex.InnerExceptions)
                    {
                        YmatouLoggingService.Error("YmtUserLoginHistoryRepository AsyncUpdateLoginTime error-0 {0}",
                            item);
                    }
                }
                catch (Exception ex)
                {
                    YmatouLoggingService.Error("YmtUserLoginHistoryRepository AsyncUpdateLoginTime error-1 {0}", ex);
                }
                finally
                {
                    if (sqlConn != null && sqlConn.State == System.Data.ConnectionState.Open)
                        sqlConn.Close();
                }
            }
        }

        public int GetUserLoginCount(string countName, string key, DateTime startTime, DateTime endTime)
        {
            var watch = Stopwatch.StartNew();
            try
            {
                var result = NaturalCounterClientAgent.GetNatualCounterList(ConfigurationManager.AppSettings["AppId"]
                    , countName
                    , key
                    , startTime, endTime);
                watch.Stop();

            
                var sum= result.Values.Sum();
                YmatouLoggingService.Debug("[GetUserLoginCount] Counter Service response OK, run {0} ms,key {1} value {2}",
                watch.Elapsed.TotalMilliseconds,key,sum);
                return sum;
            }
            catch (Exception ex)
            {
                watch.Stop();
                YmatouLoggingService.Error("[GetUserLoginCount] request Counter Service excepation,loginId {0} run {1} ms,ex {2}", key,
                    watch.Elapsed.TotalMilliseconds, ex);
                return -1;
            }
        }

        public int GetLoginIpCount(string countName, string ip, DateTime startTime, DateTime endTime)
        {
            var watch = Stopwatch.StartNew();
            try
            {
                var result = NaturalCounterClientAgent.GetNatualCounterList(ConfigurationManager.AppSettings["AppId"]
                  , countName
                  , ip
                  , startTime, endTime);
                watch.Stop();
                var sum = result.Values.Sum();
                YmatouLoggingService.Debug("[GetLoginIpCount] Counter Service response OK, run {0} ms,key {1},countType {2} value {3}",
                watch.Elapsed.TotalMilliseconds, ip,countName, sum);
                return sum;
            }
            catch (Exception ex)
            {
                watch.Stop();
                YmatouLoggingService.Error("[GetLoginIpCount] request Counter Service excepation,key {0},countType {1} run {2} ms,ex {3}", ip,
                    countName,watch.Elapsed.TotalMilliseconds, ex.ToString());
                return -1;
            }          
        }

        /// <summary>
        /// 查询在 {countStartTime} 分钟内 设备/ClientId 登录 成功/失败（success）的次数
        /// </summary>
        /// <param name="deviceType"></param>
        /// <param name="deviceId"></param>
        /// <param name="success"></param>
        /// <param name="countStartTime"></param>
        /// <returns></returns>
        public int GetLoginDeviceCount(byte deviceType, string deviceId, bool success, int countStartTime)
        {
            var watch = Stopwatch.StartNew();
            int result = 0;
            string targetId = LoginEventSpecifications.GenerateLoginDeviceSpecKey(deviceType, deviceId, success);
            try
            {
                var _time = countStartTime > 0 ? DateTime.Now.AddMinutes(-countStartTime) : DateTime.Now.AddMinutes(countStartTime);
                string counter = string.Empty;
                if (success)
                    counter = LoginEventSpecifications.AUTHSERVICE_LOGIN_DEVICE_SUCCESS_KEY;
                else
                    counter = LoginEventSpecifications.AUTHSERVICE_LOGIN_DEVICE_FAIL_KEY;

                // result = NaturalCounterClientAgent.GetNatualCounter(ConfigurationManager.AppSettings["AppId"], counter, targetId, _time);

                GetNaturalCounterListRequest counterReq = new GetNaturalCounterListRequest
                {
                    AppId = ConfigurationManager.AppSettings["AppId"],
                    Counter = counter,
                    TargetId = targetId,
                    StartTime = _time,
                    EndTime = DateTime.Now
                };

                GetNaturalCounterListResponse counterRes = ServiceClient.Execute<GetNaturalCounterListRequest, GetNaturalCounterListResponse>(counterReq);
                watch.Stop();

                if (counterRes.Code == StatusCode.Success)
                {
                    result = counterRes.Data.Sum(kv => kv.Value);
                }

                YmatouLoggingService.Debug("[GetLoginDeviceCount] Counter Service response OK, run {0} ms,targetId {1},value {2}", watch.Elapsed.TotalMilliseconds, targetId, result);

                return result;
            }
            catch (Exception ex)
            {
                watch.Stop();
                YmatouLoggingService.Error(string.Format("[GetLoginDeviceCount] request Counter Service excepation,targetId {0},run {1} ms,ex {2}", targetId, watch.Elapsed.TotalMilliseconds, ex.ToString()), ex);
                return -1;
            }
        }

        public int IncrementLoginIpCount(string countName, string ip, bool success)
        {
            return NaturalCounterClientAgent.IncreaseNatualCounter(ConfigurationManager.AppSettings["AppId"], countName,
                ip,
                DateTime.Now.AddMinutes(1));
        }
    }
}
